﻿using System;
using System.Threading;
using System.Windows.Forms;
using Plugins.Controls;
using Plugins.Core;
using Plugins.Core.Interfaces;
using Plugins.Engine;
using Plugins.Interfaces;

namespace Plugins.Samples
{
    public partial class PluginHostWindow : PluginWindow
    {
        private IPluginManagerWindow _pluginManagerWindow;
        private IPluginLoadWindow _pluginSplashScreen;
        private IPluginManager _pluginManager;

        private IPluginConfiguration[] _confugurations = new IPluginConfiguration[1];

        public PluginHostWindow()
        {
            InitializeComponent();
            this.InitializeSplashScreen();
        }

        private void InitializeSplashScreen()
        {
            this._pluginSplashScreen = new PluginLoadWindow();
            this._pluginSplashScreen.ConfigurationCount = _confugurations.Length;

            this._pluginManager = new PluginManager();
            this._pluginManager.LoadConfiguration += (object obj, PluginConfigurationHostEventArgs e) =>
            {
                _pluginSplashScreen.LoadConfiguration(e.Configuration);
            };
            this._pluginManager.UnloadConfiguration += (object obj, PluginConfigurationHostEventArgs e) =>
            {
                _pluginSplashScreen.UnloadConfiguration(e.Configuration);
            };

            this._pluginManagerWindow = new PluginManagerWindow();
            this._pluginManagerWindow.NotifyOpen += new EventHandler<PluginWindowEventArgs>(PluginWindow_NotifyOpen);
            this._pluginManagerWindow.NotifyClose += new EventHandler<PluginWindowEventArgs>(PluginWindow_NotifyClose);
        }

        private void PluginWindow_NotifyOpen(object sender, PluginWindowEventArgs e)
        {
            IPluginWindow window = WindowManager.GetWindow(e.Name);
            if (window != null)
            {
                WindowManager.Attach(window);
            }
        }

        private void PluginWindow_NotifyClose(object sender, PluginWindowEventArgs e)
        {
            IPluginWindow window = WindowManager.GetWindow(e.Name);
            if (window != null)
            {
                WindowManager.Detach(window);
            }
        }

        private void PluginWindow_Load(object sender, EventArgs e)
        {
            LoadManagerWindow();
            LoadWindow();
        }

        private void PluginWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnloadWindow();
            UnloadManagerWindow();
        }

        private void LoadWindow()
        {
            LoadOptions("options.xml");
            LoadSplashScreen();
            LoadWindowState();
            LoadPopupWindows();
        }

        private void UnloadWindow()
        {
            UnloadPopupWindows();
            UnloadWindowState();
            UnloadSplashScreen();
            UnloadOptions("options.xml");
        }

        private void LoadManagerWindow()
        {
            WindowManager.Register(_pluginManagerWindow);
            _pluginManagerWindow.Attach(DefaultOptions);
            _pluginManagerWindow.Attach(this);
        }

        private void UnloadManagerWindow()
        {
            _pluginManagerWindow.Detach(this);
            _pluginManagerWindow.Detach(DefaultOptions);
            WindowManager.Unregister(_pluginManagerWindow);
        }

        private void LoadSplashScreen()
        {
            this.WindowState = FormWindowState.Minimized;
            _pluginSplashScreen.Popup(false);
            LoadConfiguration();
        }

        private void UnloadSplashScreen()
        {
            this.WindowState = FormWindowState.Minimized;
            _pluginSplashScreen.Popup(true);
            UnloadConfiguration();
        }

        private void PopupWindow()
        {
            Popup(this, _pluginManagerWindow);
        }

        private void RegisterOptions()
        {
            for (int i = 0; i < _confugurations.Length; i++)
            {
                RegisterOptions(_confugurations[i]);
            }
        }

        private void UnregisterOptions()
        {
            for (int i = 0; i < _confugurations.Length; i++)
            {
                UnregisterOptions(_confugurations[i]);
            }
        }

        private void RegisterOptions(IPluginConfigurationHost host)
        {
            this._pluginManagerWindow.RegisterHost(host);
        }

        private void UnregisterOptions(IPluginConfigurationHost host)
        {
            this._pluginManagerWindow.UnregisterHost(host);
        }

        private void LoadConfiguration()
        {
#if _DEBUG_
            PluginLog.WriteSync(">>> online");
#endif

            _confugurations[0] = _pluginManager.Load<IPluginManagerWindow>("00000000-0000-0000-0000-000000000000", "default", "plugins.xml", true);

            RegisterOptions();
        }

        private void UnloadConfiguration()
        {
            UnregisterOptions();

            _pluginManager.Unload<IPluginManagerWindow>(_confugurations[0]);

#if _DEBUG_
            PluginLog.WriteSync("<<< offline");
#endif
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PopupWindow();
        }
    }
}
